/**
 * All Rights Reserved , Copyright (C) 2021 , 青岛鼎信通讯股份有限公司
 * BaseTableExtendService
 * 系统扩展表
 * 修改纪录
 * 2021-03-12 版本：1.0 zhanglongfei 创建。
 * 
 * @version 版本：1.0
 * @author 作者：zhanglongfei
 * 创建日期：2021-03-12
 */
package com.topscomm.base.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.topscomm.base.service.IBaseTableExtendService;
import com.topscomm.base.service.impl.auto.BaseTableExtendServiceAuto;
import com.topscomm.cbo.pojo.CboApprovalFlowInsEntity;
import com.topscomm.cbo.pojo.CboApprovalNodeEntity;
import com.topscomm.cbo.pojo.CboApprovalNodeInsEntity;
import com.topscomm.cbo.pojo.CboDeptEntity;
import com.topscomm.cbo.pojo.CboOrgEntity;
import com.topscomm.cbo.pojo.CboUserEntity;
import com.topscomm.cbo.service.ICboApprovalFlowInsService;
import com.topscomm.cbo.service.ICboApprovalLineService;
import com.topscomm.cbo.service.ICboApprovalNodeInsService;
import com.topscomm.cbo.service.ICboApprovalNodeService;
import com.topscomm.cbo.service.ICboDeptService;
import com.topscomm.cbo.service.ICboOrgService;
import com.topscomm.cbo.service.ICboUserService;
import com.topscomm.meet.api.MeetServiceApi;
import com.topscomm.pub.util.ConvertUtil;
import com.topscomm.pub.util.SpringUtil;
import com.topscomm.pub.util.StringBufferProxy;
import com.topscomm.pub.util.StringUtil;
import com.topscomm.sys.pojo.SysApiLogEntity;
import com.topscomm.sys.service.ISysApiLogService;
import com.topscomm.tap.ITapService;
import com.topscomm.tap.TapService;
import com.topscomm.tap.common.ParameterCache;
import com.topscomm.tap.common.SessionUserBean;
import com.topscomm.tap.common.TapSystemConst.TapApprovalNodeStateEnum;

@Service(value = "baseTableExtendService")
@Scope(value = "singleton")
public class BaseTableExtendService extends BaseTableExtendServiceAuto implements IBaseTableExtendService {
	@Autowired
	ICboApprovalNodeInsService cboApprovalNodeInsService;
	@Autowired
	ICboApprovalNodeService cboApprovalNodeService;
	@Autowired
	ICboUserService cboUserService;
	@Autowired
	ICboDeptService cboDeptService;
	@Autowired
	ICboOrgService cboOrgService;
	@Autowired
	ICboApprovalFlowInsService cboApprovalFlowInsService;
	@Autowired
	ICboApprovalLineService cboApprovalLineService;
	@Autowired
	ISysApiLogService sysApiLogService;
	@Autowired
	MeetServiceApi meetServiceApi;

	/**
	 * @description:自定义退回
	 * @param paraMap
	 * @author: zhanglongfei
	 * @date: 2021年3月16日上午11:20:26
	 * @modify:
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void customizeBack(Map<String, Object> paraMap) {
		String flowInsId = ConvertUtil.convertToString(paraMap.get("flowinsid"));
		String userId = ConvertUtil.convertToString(paraMap.get("userid"));
		String backNodeId = ConvertUtil.convertToString(paraMap.get("backnodeid"));
		String sourceType = ConvertUtil.convertToString(paraMap.get("sourcetype"));
		String opinion = ParameterCache.getValue("BaseCustomizeBackOpinion", "项目发起人主动退回到指定节点");
		// 删除对应日程
		delWorkSchedule(flowInsId, backNodeId);
		SessionUserBean userBean = null;
		CboUserEntity userEntity = cboUserService.queryById(userId);
		if (userEntity != null) {
			userBean = new SessionUserBean();
			userBean.setUser(userEntity);
			CboDeptEntity deptEntity = cboDeptService.queryById(userEntity.getDeptid() + "");
			userBean.setDept(deptEntity);
			CboOrgEntity orgEntity = cboOrgService.queryById(userEntity.getOrgid() + "");
			userBean.setOrg(orgEntity);
		}
		ITapService<?, ?> tapService = (TapService<?, ?>) SpringUtil.getBean(StringUtil.lowerFirst(sourceType) + "Service");
		// 获取所有未审批的节点，驳回
		// void executeApprove(String nodeInsId, Date approvalDate, String approvalOpinion, String approvalType,
		// String backNodeId, SessionUserBean sessionUserBean, Long nextUserId);
		List<CboApprovalNodeInsEntity> nodeInsList = cboApprovalNodeInsService.queryByWhere("flowinsid='" + flowInsId + "' and state=1");
		if (nodeInsList == null || nodeInsList.size() == 0)
			return;
		// for (CboApprovalNodeInsEntity nodeIns : nodeInsList) {
		// execApprovalBack(tapService, userBean, flowInsId, opinion, backNodeId, nodeIns);
		// }
		// 退回第一个节点，然后其他节点关闭
		execApprovalBack(tapService, userBean, flowInsId, opinion, backNodeId, nodeInsList.get(0));
		StringBufferProxy sql = new StringBufferProxy();
		for (int i = 1, max = nodeInsList.size(); i < max; i++) {
			CboApprovalNodeEntity nodeEntity = cboApprovalNodeService.queryById(nodeInsList.get(0).getNodeid() + "");
			if (nodeEntity.getNodetype() == 3 || nodeEntity.getNodetype() == 4) {
				execApprovalBack(tapService, userBean, flowInsId, opinion, backNodeId, nodeInsList.get(0));
			} else {
				sql.clear();
				sql.appendSingle(" update {0} set state = {1}, {2}='{3}' where id={4} and state = '1' ", CboApprovalNodeInsEntity.tableName, TapApprovalNodeStateEnum.Close, CboApprovalNodeInsEntity.FieldApprovalopinion, opinion, nodeInsList
						.get(i).getId());
				cboApprovalNodeInsService.updateExecute(sql.toString());
			}
		}
	}

	/**
	 * @description:执行退回到指定节点的功能
	 * @param tapService
	 * @param userBean
	 * @param flowInsId
	 * @param approvalOpinion
	 * @param backNodeId
	 * @author: zhanglongfei
	 * @date: 2021年3月16日下午2:50:50
	 * @modify:
	 */
	private void execApprovalBack(ITapService<?, ?> tapService, SessionUserBean userBean, String flowInsId, String approvalOpinion, String backNodeId, CboApprovalNodeInsEntity nodeIns) {
		// 获取一下这个节点的最新状态，可能在之前一个节点驳回时，已经顺便更新了
		CboApprovalNodeInsEntity newNodeInsEntity = cboApprovalNodeInsService.queryById(nodeIns.getId() + "");
		if (newNodeInsEntity.getState() != 1)
			return;
		// 由于审批方法，会判断退回表达式，才会执行退回到指定节点，所以需要更新下，再更新回来
		CboApprovalNodeEntity nodeEntity = cboApprovalNodeService.queryById(nodeIns.getNodeid() + "");
		String oldExp = nodeEntity.getBackexp();
		if (StringUtil.isEmpty(oldExp)) {
			oldExp = "";
		}
		cboApprovalNodeService.updateExecute("update CboApprovalNode set backexp='NodeIds:' where id=" + nodeEntity.getId());
		tapService.executeApprove(nodeIns.getId() + "", new Date(), approvalOpinion, "2", backNodeId, userBean, 0L);
		cboApprovalNodeService.updateExecute("update CboApprovalNode set backexp='" + oldExp + "' where id=" + nodeEntity.getId());
	}

	/**
	 * @description: 退回时删除对接日程及流程活动的日程
	 * @param flowInsId
	 * @param backNodeId
	 * @author: maxiaodong
	 * @date: 2021年3月24日下午5:14:08
	 * @modify:
	 */
	private void delWorkSchedule(String flowInsId, String backNodeId) {
		CboApprovalFlowInsEntity cboApprovalFlowInsEntity = cboApprovalFlowInsService.queryById(flowInsId);
		String sourcetype = ConvertUtil.convertToString(cboApprovalFlowInsEntity.getSourcetype());
		String sourceid = ConvertUtil.convertToString(cboApprovalFlowInsEntity.getSourceid());
		// 获得退回的所有节点实例
		List<CboApprovalNodeInsEntity> backedNodeEntityList = queryBackedNodeEntityList(flowInsId, backNodeId);
		Set<String> backedNodeInsSet = new HashSet<>();
		for (CboApprovalNodeInsEntity cboApprovalNodeInsEntity : backedNodeEntityList) {
			backedNodeInsSet.add(ConvertUtil.convertToString(cboApprovalNodeInsEntity.getId()));
		}
		// 获得该流程实例调用的日程添加接口历史记录
		StringBufferProxy queryApiLogSql = new StringBufferProxy();
		queryApiLogSql.appendSingle("sourcetype like '{0}%' and sourceid in ('{1}') and url like '%{2}'", sourcetype, sourceid, "mulitSubmitWorkSchedule");
		List<SysApiLogEntity> sysApiLogEntityList = sysApiLogService.queryByWhere(queryApiLogSql.toString());
		// 对退回节点发送的日程删除并删除历史记录
		for (SysApiLogEntity sysApiLogEntity : sysApiLogEntityList) {
			// 若存在发送日程的记录，删除该日程并删除该记录
			if (backedNodeInsSet.contains(sysApiLogEntity.getExtendfield1())) {
				meetServiceApi.cancelWorkSchedule("mcr", sysApiLogEntity.getSourcetype(), sysApiLogEntity.getSourceid());
				StringBufferProxy deleteSql = new StringBufferProxy();
				deleteSql
						.appendSingle("sourcetype like '{0}%' and sourceid in ('{1}') and url like '%{2}' and  {3} in ('{4}')", sourcetype, sourceid, "mulitSubmitWorkSchedule", SysApiLogEntity.FieldExtendfield1, ConvertUtil
								.convertToString(sysApiLogEntity.getExtendfield1()));
				sysApiLogService.deleteByWhere(deleteSql.toString());
			}
		}
	}

	/**
	 * @description: 获得退回的所有节点实例
	 * @param flowInsId-流程实例id
	 * @param backNodeId-退回节点的id
	 * @author: maxiaodong
	 * @return
	 * @date: 2021年3月18日下午7:56:06
	 * @modify:
	 */
	public List<CboApprovalNodeInsEntity> queryBackedNodeEntityList(String flowInsId, String backNodeId) {
		// 获得该流程实例下的所有节点实例
		StringBufferProxy sql = new StringBufferProxy();
		sql.appendSingle("flowinsid in ({0}) order by createon desc", flowInsId);
		List<CboApprovalNodeInsEntity> cboApprovalNodeInsEntityList = cboApprovalNodeInsService.queryByWhere(sql.toString());
		List<CboApprovalNodeInsEntity> result = new ArrayList<>();
		Boolean lastEqual = false;
		for (CboApprovalNodeInsEntity cboApprovalNodeInsEntity : cboApprovalNodeInsEntityList) {
			String nodeId = ConvertUtil.convertToString(cboApprovalNodeInsEntity.getNodeid());
			if (backNodeId.equals(nodeId)) {
				// 若该次判断为等于，则加入result，并继续遍历
				result.add(cboApprovalNodeInsEntity);
				lastEqual = true;
			} else {
				// 若该次判断为不等于，则根据上次结果判断情况
				if (lastEqual == false) {
					// 若上次结果为不等于，则加入result，并继续遍历
					result.add(cboApprovalNodeInsEntity);
					lastEqual = false;
				} else {
					// 若上次结果为等于，则返回result
					return result;
				}
			}
		}
		return result;
	}
}
